PSR-13: Link definition interfaces
本文
RFC 5988 - Web Linkingを踏まえてPHPのインターフェイスとして定義したもので、ざっくり言うとHTMLの<a href="...">や<link rel="..." href="...">を抽象化したもの。 Psr\Link\LinkInterface
Psr\Link\EvolvableLinkInterface
Psr\Link\LinkProviderInterface
Psr\Link\EvolvableLinkProviderInterface
PHP-FIGが提供するユーティリティクラス
code:php
/**
* Returns the target of the link.
*
* The target link must be one of:
* - An absolute URI, as defined by RFC 5988.
* - A relative URI, as defined by RFC 5988. The base of the relative link
* is assumed to be known based on context by the client.
* - A URI template as defined by RFC 6570.
*
* If a URI template is returned, isTemplated() MUST return True.
*
* @return string
*/
public function getHref();
内部的に持っているURIとは「絶対URI」「相対URI」そしてそれぞれがテンプレート化されたものがあり、そのどれであってもstringで返せ、と言っているのでる。このURIの素性が何者であるかを静的に判別できる要素はない。
PHP-FIGはPSRのインターフェイスとは別に実装者の便宜のためにユーティリティクラスを提供しているが、以下のようなtraitを提供している。 code:php
/**
* Determines if an href is a templated link or not.
*
*
* @param string $href
* The href value to check.
*
* @return bool
* True if the specified href is a templated path, False otherwise.
*/
private function hrefIsTemplated($href)
{
return strpos($href, '{') !== false ||strpos($href, '}') !== false;
}
セキュアプログラミングの原則に反するコードだ。Syntaxのあるテンプレート言語を検出するコードとは思えない乱雑さのコードであり、典型的な脆弱性の温床となりうる。とても標準化を標榜する団体が提供する実装のコードだとは思えない。
たとえば$_SERVER['REQUEST_URI']から取得した文字列を使ってLinkオブジェクトを作りたいとする。
code:php
<?php
var_dump([
'$_GET' => $_GET,
]);
Google ChromeのようなWebブラウザから http://localhost:3939/{}?a={} にアクセスするとコマンドラインから上記のスクリプトにphp -r 'readfile("http://localhost:3939/{}?a={}");'のようなPHPスクリプトで受けるページにリクエストすると、{}はエスケープされない。
Symfony/WebLink
もともとはSymfonyもFig\Linkを使っていたが、この実装はコピーされる形で Symfony\Component\WebLink\Link::hrefIsTemplated()でも無批判に踏襲されている。
以上のような問題があり、たとえばファイル名に { を含むようなURIをURLエンコードせずに渡すと無視されることになる。